<template>
    <el-dialog v-model="isOpen" title="聚类分析结果" width="800" :border="true" align-center>
        <div class="eChartContainer flex-row justify-center align-center">
            <div ref="chartRef" class="chart" />
        </div>

        <template #footer>
            <el-button type="primary" @click="isOpen = false">关闭</el-button>
        </template>
    </el-dialog>
</template>

<script setup>
import { nextTick, ref, watch } from "vue"
import * as echarts             from "echarts"

let isOpen = defineModel()
let props  = defineProps([ "originalData", "result" ])

const chartRef    = ref(null)
let chartInstance = null

const getFeatureNames = () => {
    if(!props.originalData?.listColumn || props.originalData.listColumn.length < 2){
        return [ "特征1", "特征2" ] // 默认名称
    }
    return props.originalData.listColumn.map(item => item.key)
}

// 从原始数据中获取对应索引的完整信息
const getOriginalDataItem = (index) => {
    if(!props.originalData?.listAll || !props.originalData.listAll[index]){
        return { "序号": "未知", "门店名称": "未知" }
    }
    return props.originalData.listAll[index]
}

watch(isOpen, (val) => {
    if(val){
        initChart()
    }
})

const initChart = () => {
    nextTick(() => {
        if(!chartRef.value || !props.result){
            return
        }

        if(!chartInstance){
            chartInstance = echarts.init(chartRef.value)
        }

        // 解构结果数据
        const {
                  clusterLabels = [],
                  centroids     = [],
                  iterations    = 0,
                  inertia       = 0,
                  computeTime   = 0,
                  k             = centroids.length,
              } = props.result

        // 获取特征名称（横纵轴标签）
        const [ xAxisName, yAxisName ] = getFeatureNames()

        // 处理原始数据：关联聚类标签和完整原始信息
        const rawData = clusterLabels.map((cluster, index) => {
            const originalItem = getOriginalDataItem(index)
            return {
                x: Number(originalItem[xAxisName] || 0),  // X轴值
                y: Number(originalItem[yAxisName] || 0),  // Y轴值
                cluster,
                originalItem,  // 保存完整原始数据
            }
        })

        // 按聚类分组数据（包含原始信息）
        const seriesData = Array.from({ length: k }, (_, clusterIndex) =>
            rawData
            .filter(item => item.cluster === clusterIndex)
            .map(item => ({
                value       : [ item.x, item.y ],
                originalItem: item.originalItem,  // 携带原始数据到图表中
            })),
        )

        // 聚类样式配置
        const clusterColors = [ "#409eff", "#67c23a", "#f56c6c", "#909399", "#e6a23c" ]
        const clusterNames  = Array.from({ length: k }, (_, i) => `聚类 ${ i + 1 }`)

        const option = {
            title  : [
                {
                    text     : `迭代次数: ${ iterations }`,
                    left     : "20%",
                    top      : 10,
                    textStyle: { fontSize: 14, color: "#606266" },
                },
                {
                    text     : `误差平方和: ${ inertia.toFixed(2) }`,
                    left     : "50%",
                    top      : 10,
                    textStyle: { fontSize: 14, color: "#606266" },
                },
                {
                    text     : `计算时间: ${ computeTime }ms`,
                    left     : "80%",
                    top      : 10,
                    textStyle: { fontSize: 14, color: "#606266" },
                },
            ],
            tooltip: {
                trigger  : "item",
                formatter: params => {
                    // 质心提示
                    if(params.seriesName.includes("质心")){
                        return `${ params.seriesName }<br>
                                ${ xAxisName }: ${ params.value[0].toFixed(2) }<br>
                                ${ yAxisName }: ${ params.value[1].toFixed(2) }`
                    }

                    // 数据点提示（包含原始数据信息）
                    const original  = params.data.originalItem
                    let tooltipHtml = `<strong>${ params.seriesName }</strong><br>`
                    // 遍历原始数据的所有字段
                    Object.entries(original).forEach(([ key, value ]) => {
                        tooltipHtml += `${ key }: ${ value }<br>`
                    })
                    return tooltipHtml
                },
            },
            legend : {
                data: [ ...clusterNames, "聚类质心" ],
                top : 40,
            },
            grid   : {
                left        : "8%",
                right       : "5%",
                bottom      : "10%",
                containLabel: true,
            },
            xAxis  : {
                type        : "value",
                name        : xAxisName,
                nameLocation: "middle",
                nameGap     : 30,
                axisLabel   : { formatter: val => val.toFixed(1) },
            },
            yAxis  : {
                type        : "value",
                name        : yAxisName,
                nameLocation: "middle",
                nameGap     : 50,
                axisLabel   : { formatter: val => val.toFixed(1) },
            },
            series : [
                // 聚类数据点（携带原始信息）
                ...seriesData.map((data, index) => ({
                    name      : clusterNames[index],
                    type      : "scatter",
                    data      : data,  // 包含value和originalItem
                    symbolSize: 15,
                    itemStyle : { color: clusterColors[index % clusterColors.length] },
                    emphasis  : {
                        focus    : "series",
                        itemStyle: { shadowBlur: 10, shadowColor: "rgba(0, 0, 0, 0.3)" },
                    },
                })),
                // 聚类质心
                {
                    name      : "聚类质心",
                    type      : "scatter",
                    data      : centroids.map(centroid => [
                        Number(centroid[0]),
                        Number(centroid[1]),
                    ]),
                    symbol    : "diamond",
                    symbolSize: 20,
                    itemStyle : {
                        color      : "#e6a23c",
                        borderWidth: 2,
                        borderColor: "#fff",
                    },
                    label     : {
                        show     : true,
                        formatter: `质心`,
                        position : "bottom",
                    },
                },
            ],
        }

        chartInstance.setOption(option)
    })
}

</script>

<style scoped>
.eChartContainer {
    width: 100%;
    height: 500px;
    padding: 10px 0;

    .chart {
        width: 100%;
        height: 100%;
    }
}
</style>

